package common_sign

import (
	eJson "encoding/json"
	"gitee.com/xlizy/common-go/base/common_config"
	"gitee.com/xlizy/common-go/utils/common_crypto"
	"gitee.com/xlizy/common-go/utils/json"
	"gitee.com/xlizy/common-go/utils/zlog"
	"sort"
	"time"
)

func GenSign(obj any, app string) string {
	objCopy := make(map[string]any)
	jsonStr := json.ToJsonStr(obj)
	json.ToObj(jsonStr, &objCopy)
	objCopy["sign"] = nil
	result, _ := sortJSONComplex(json.ToJsonStr(objCopy))
	appSK := "W4v0s1yoyvpYADUHeNpgbrTpu6a2cgEC"
	if common_config.AppSign.Sign[app] != "" {
		appSK = common_config.AppSign.Sign[app]
	} else if app != "" {
		appSK = app
	}
	origin := result + appSK
	return common_crypto.Md5(origin)
}

func CheckSign(obj any, app string) bool {
	objCopy := make(map[string]any)
	jsonStr := json.ToJsonStr(obj)
	json.ToObj(jsonStr, &objCopy)
	reqSign := objCopy["sign"]
	objCopy["sign"] = nil
	result, _ := sortJSONComplex(json.ToJsonStr(objCopy))
	appSK := "W4v0s1yoyvpYADUHeNpgbrTpu6a2cgEC"
	if common_config.AppSign.Sign[app] != "" {
		appSK = common_config.AppSign.Sign[app]
	} else if app != "" {
		appSK = app
	}
	origin := result + appSK
	sign := common_crypto.Md5(origin)
	if reqSign != sign {
		zlog.Info("签名前字符串:{}", origin)
		zlog.Info("验签失败:签名错误,{}:{}", reqSign, sign)
		return false
	}
	if timestamp, exists := objCopy["timestamp"]; exists {
		switch tv := timestamp.(type) {
		case float64:
			t := time.UnixMilli(int64(tv))
			if time.Now().After(t.Add(7 * 24 * time.Hour)) {
				zlog.Info("验签失败:数据过期")
				return false
			} else {
				return true
			}
		case int64:
			t := time.UnixMilli(tv)
			if time.Now().After(t.Add(7 * 24 * time.Hour)) {
				zlog.Info("验签失败:数据过期")
				return false
			} else {
				return true
			}
		default:
			zlog.Info("验签失败:时间戳格式错误")
			return false
		}
	} else {
		return true
	}
}

func sortJSONComplex(jsonStr string) (string, error) {
	var data interface{}
	// 1. 将JSON字符串解析为interface{}，以处理更复杂结构
	err := eJson.Unmarshal([]byte(jsonStr), &data)
	if err != nil {
		return "", err
	}

	sortedData, err := sortInterface(data)
	if err != nil {
		return "", err
	}

	sortedJSONBytes, err := eJson.Marshal(sortedData)
	if err != nil {
		return "", err
	}
	return string(sortedJSONBytes), nil
}

func sortInterface(v interface{}) (interface{}, error) {
	switch v := v.(type) {
	case map[string]interface{}:
		keys := make([]string, 0, len(v))
		for k := range v {
			keys = append(keys, k)
		}
		sort.Strings(keys)

		sortedMap := make(map[string]interface{})
		for _, k := range keys {
			if v[k] == nil {
				continue
			}
			sortedValue, err := sortInterface(v[k])
			if err != nil {
				return nil, err
			}
			sortedMap[k] = sortedValue
		}
		return sortedMap, nil
	case []interface{}:
		sortedSlice := make([]interface{}, len(v))
		for i, element := range v {
			sortedElement, err := sortInterface(element)
			if err != nil {
				return nil, err
			}
			sortedSlice[i] = sortedElement
		}
		return sortedSlice, nil
	default:
		return v, nil
	}
}
